package com.ecahack.busstop.activities;

import java.io.IOException;
import java.io.Serializable;
import java.util.List;

import org.json.JSONException;

import android.content.Intent;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.widget.SearchView;
import com.actionbarsherlock.widget.SearchView.OnQueryTextListener;
import com.ecahack.busstop.R;
import com.ecahack.busstop.data.BusStop;
import com.ecahack.busstop.json.BusStopListGrabber;
import com.ecahack.busstop.json.JSONParser;
import com.ecahack.busstop.utils.StopListViewAdapter;

public class MainActivity extends BaseBusStopActivity {

	public static final String BUS_STOP_ID = "bus_stop_id";
	public static final String BUS_STOPS = "bus_stops";
	public static final String TAG = MainActivity.class.getSimpleName();
	public static final String STOP_DIALOG_TAG = "StopDialog";
	public static final String CURRENT_LOCATION_LAT = "current_location_lat";
	public static final String CURRENT_LOCATION_LONG  = "current_location_long";

	public static final int STOP_LOCATION_ID_DEFAULT_VALUE = -117;
	private static final String SEARCH_TARGET_KEY = "search_target_key";

	private Menu mMenu;
	SearchView searchView;
	private ImageView mResultImage;
	private TextView mResultText;
	private ProgressBar mLoading;
	private ListView mBusStopsListView;
	private StopListViewAdapter mBusStopListViewAdapter;
	private double mCurrLatitude;
	private double mCurrLongitude;

	private LoadBusStopListTask mBusStopListLoader;

	private boolean mIsDefaultSearch = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initialiseView();
		setAdapters();
		setListeners();

		if (savedInstanceState == null) {
			mIsDefaultSearch = true;
		} else {
			mIsDefaultSearch = savedInstanceState.getBoolean(SEARCH_TARGET_KEY);
		}
		startLoadBusStopListTask();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.main_activity_menu, menu);
		mMenu = menu;

		addSearchInMenu();
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.refresh:
			startLoadBusStopListTask();
			break;
		default:
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onRestart() {
		super.onRestart();
		startLoadBusStopListTask();
	}

	private void startLoadBusStopListTask() {
		if (mBusStopListLoader == null) {
			setLoading(mIsDefaultSearch);
			if (isGpsEnabled() || isNetworkEnabled()) {
				mBusStopListLoader = new LoadBusStopListTask(10);
				mBusStopListLoader.execute();
			}
		} else {
			Log.v(TAG, "BusStopListLoader is already in progress");
		}
	}

	private void addSearchInMenu() {

		searchView = new SearchView(getSupportActionBar().getThemedContext());
		searchView.setQueryHint("Search for busstops");
		searchView.setIconified(true);
		searchView.clearFocus();
		searchView.setOnQueryTextListener(new OnQueryTextListener() {

			@Override
			public boolean onQueryTextSubmit(String query) {
				Toast.makeText(MainActivity.this, query, Toast.LENGTH_SHORT)
						.show();
				return false;
			}

			@Override
			public boolean onQueryTextChange(String newText) {
				Toast.makeText(MainActivity.this, newText, Toast.LENGTH_SHORT)
						.show();
				return false;
			}
		});

		mMenu.findItem(R.id.search_autocomplete).setActionView(searchView);
	}

	private void initialiseView() {
		mBusStopsListView = (ListView) findViewById(R.id.lvBusStops);
		mResultImage = (ImageView) findViewById(R.id.ivResultImage);
		mResultText = (TextView) findViewById(R.id.tvResultText);
		mLoading = (ProgressBar) findViewById(R.id.pbLoading);
		mLoading.getIndeterminateDrawable().setColorFilter(0xFF0099cc, android.graphics.PorterDuff.Mode.MULTIPLY);
	}

	private void setAdapters() {
		mBusStopListViewAdapter = new StopListViewAdapter(this);
		mBusStopsListView.setAdapter(mBusStopListViewAdapter);
	}

	private void setListeners() {
		mBusStopsListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				BusStop selected = mBusStopListViewAdapter.getItem(position);
				Intent intent = new Intent(MainActivity.this, StopActivity.class);
				intent.putExtra(BUS_STOP_ID, selected.getLocationId());
				intent.putExtra(BUS_STOPS, (Serializable)mBusStopListViewAdapter.getList());
				intent.putExtra(CURRENT_LOCATION_LAT, mCurrLatitude);
				intent.putExtra(CURRENT_LOCATION_LONG, mCurrLongitude);
				startActivity(intent);
			}
		});
	}

	private void setSearchSuccsess(boolean success, boolean forCurrentLocation,
			String additionalMessage) {

		mLoading.setVisibility(View.INVISIBLE);
		mResultImage.setVisibility(View.VISIBLE);

		if (success) {
			mResultText.setTextColor(0xFF0099cc);
			mResultImage.setImageDrawable(getResources().getDrawable(
					R.drawable.success));
			if (forCurrentLocation) {
				mResultText.setText(R.string.success_text_current);
			} else {
				mResultText.setText(R.string.success_text);
			}
		} else {
			mResultImage.setImageDrawable(getResources().getDrawable(
					R.drawable.failure));
			mResultText.setTextColor(0xFFFF0000);
			if (forCurrentLocation)
				mResultText.setText(R.string.failure_text_current);
			else
				mResultText.setText(R.string.failure_text);
		}

		if (additionalMessage != null) {
			mResultText.setText(Html.fromHtml(additionalMessage));
		}
	}

	public void setLoading(boolean forCurrentLocation) {

		mLoading.setVisibility(View.VISIBLE);
		mResultImage.setVisibility(View.INVISIBLE);

		if (forCurrentLocation)
			mResultText.setText(R.string.searching_current);
		else
			mResultText.setText(R.string.searching_text);
		
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putBoolean(SEARCH_TARGET_KEY, mIsDefaultSearch);
	}

	private class LoadBusStopListTask extends AsyncTask<Void, Void, List<BusStop>> {

		private static final String TAG = "LoadBusStopListTask";

		private int mQuantity;
		private boolean mJsonError;
		private boolean mIOError;
		private boolean mLocationUnavailable;

		public LoadBusStopListTask(int quantity) {
			mQuantity = quantity;
		}

		@Override
		protected void onPreExecute() {
			setLoading(mIsDefaultSearch);
		}

		@Override
		protected List<BusStop> doInBackground(Void... params) {
			Location location = getCurrentLocation();
			
			if (location != null) {
				mCurrLatitude = location.getLatitude();
				mCurrLongitude = location.getLongitude();
				JSONParser parser = JSONParser.getInstance();
				BusStopListGrabber busStopListGrabber = BusStopListGrabber
						.getInstance(parser);
				try {
					return busStopListGrabber.grabBusStopList(location,
							mQuantity);
				} catch (JSONException e) {
					Log.e(TAG, "Unable to get bus stop list", e);
					mJsonError = true;
					return null;
				} catch (IOException e) {
					Log.w(TAG, "Caught IOException while getting busstop list",
							e);
					mIOError = true;
					return null;
				}
			} else {
				mLocationUnavailable = true;
			}
			return null;
		}

		@Override
		protected void onPostExecute(List<BusStop> stops) {
			if (mIOError) {
				setSearchSuccsess(false, mIsDefaultSearch, getResources()
						.getString(R.string.service_error_message));
			} else if (mJsonError) {
				setSearchSuccsess(false, mIsDefaultSearch, getResources()
						.getString(R.string.service_error_message));
			} else if (mLocationUnavailable) {
				setSearchSuccsess(false, mIsDefaultSearch, getResources()
						.getString(R.string.location_unavilable));
			}
			if (stops != null) {
				setSearchSuccsess(true, mIsDefaultSearch, buildMessage());
				mBusStopListViewAdapter.setList(stops);
				Log.i(TAG, "Fetched bus stops succesfully");
				
			} else {
				Log.v(TAG, "Bus stop list is not available");
			}

			mBusStopListLoader = null;
			// TODO: handle the case without internet
		}

		private String buildMessage() {
			String message = "";
			if (!isGpsEnabled()) {
				if (mIsDefaultSearch) {
					message += getString(R.string.success_text_current) + ", "
							+ getString(R.string.GPS_is_not_active_message);
				} else {
					message += getString(R.string.success_text) + ", "
							+ getString(R.string.GPS_is_not_active_message);
				}
			} else {
				if (mIsDefaultSearch) {
					message += getString(R.string.success_text_current);
				} else {
					message += getString(R.string.success_text);
				}
			}
			return message;
		}
	}

}
